package client.controller;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

import javax.media.j3d.Transform3D;
import javax.vecmath.Quat4d;
import javax.vecmath.Vector3d;

import server.controller.ServerObject3DController;
import client.Client;
import client.model.Object3D;
import client.presentation.Object3DPresentation;

public class Object3DController implements Virtual3DController {
	
	private Object3DPresentation presentation = null;
	private Object3D abstraction = null;
	
	public Object3DController(String name) {
		
		try {
			//On recupere les informations de l'objet sur le serveur
			ServerObject3DController c = (ServerObject3DController) Naming.lookup(Client.lookupName+"/"+name);
			Vector3d position = c.getPosition();
			Quat4d orientation = c.getOrientation();
			String vrml = c.getFileLoaded();
			
			abstraction = new Object3D(name, position, orientation, vrml);
			presentation = new Object3DPresentation(this, vrml);
			
			Transform3D transform = new Transform3D();
			transform.set(orientation, position, 1);
			presentation.setTransform(transform);
			
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (RemoteException e) {
			e.printStackTrace();
		} catch (NotBoundException e) {
			e.printStackTrace();
		} 
		
	}
	
	//Met a jour l'objet local avec les informations en parametre
	public void update(Vector3d position, Quat4d orientation) {
		abstraction.setPosition(position);
		abstraction.setOrientation(orientation);
		Transform3D transform = new Transform3D();
		transform.set(abstraction.getOrientation(), abstraction.getPosition(), 1);
		presentation.setTransform(transform);
	}

	public String getName() {
		return abstraction.getName();
	}
	
	public String getFile() {
		return abstraction.getVrml();
	}

	public Quat4d getOrientation() {
		return abstraction.getOrientation();
	}
	
	public void setOrientation(Quat4d q) {
		if (!q.equals(abstraction.getOrientation())) {
			try {
				ServerObject3DController c = (ServerObject3DController) Naming.lookup(Client.lookupName+"/"+abstraction.getName());
				c.setOrientation(q);
			} catch (MalformedURLException e) {
				e.printStackTrace();
			} catch (RemoteException e) {
				e.printStackTrace();
			} catch (NotBoundException e) {
				e.printStackTrace();
			}
		}
	}

	public Vector3d getPosition() {
		return abstraction.getPosition();
	}
	
	public void setPosition(Vector3d v) {
		if (!v.equals(abstraction.getPosition())) {
			try {
				ServerObject3DController c = (ServerObject3DController) Naming.lookup(Client.lookupName+"/"+abstraction.getName());
				c.setPosition(v);
			} catch (MalformedURLException e) {
				e.printStackTrace();
			} catch (RemoteException e) {
				e.printStackTrace();
			} catch (NotBoundException e) {
				e.printStackTrace();
			}
		}
	}

	public Object getPresentation() {
		return presentation;
	}

	public void setPresentation(Object p) {
		presentation = (Object3DPresentation)p;
	}

	public Transform3D getTransform() {
		Transform3D tmp = new Transform3D();
		tmp.set(abstraction.getOrientation(), abstraction.getPosition(), 1);
		return tmp;
	}

	//Met a jour les informations sur le serveur si elles ont changees
	public void setTransform(Transform3D t) {
		Vector3d position = new Vector3d();
		Quat4d orientation = new Quat4d();
		
		t.get(position);
		t.get(orientation);
		
		if (!position.equals(abstraction.getPosition())) {
			try {
				ServerObject3DController c = (ServerObject3DController) Naming.lookup(Client.lookupName+"/"+abstraction.getName());
				c.setPosition(position);
			} catch (MalformedURLException e) {
				e.printStackTrace();
			} catch (RemoteException e) {
				e.printStackTrace();
			} catch (NotBoundException e) {
				e.printStackTrace();
			}
		}
		
		if (!orientation.equals(abstraction.getOrientation())) {
			try {
				ServerObject3DController c = (ServerObject3DController) Naming.lookup(Client.lookupName+"/"+abstraction.getName());
				c.setOrientation(orientation);
			} catch (MalformedURLException e) {
				e.printStackTrace();
			} catch (RemoteException e) {
				e.printStackTrace();
			} catch (NotBoundException e) {
				e.printStackTrace();
			}
		}
		
	}
}
